using System;
using System.Collections.Generic;
using System.Reflection;
using System.Collections.ObjectModel;
using FireStarter.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    /// <summary>
    /// Provides a place to write custom tests for DMAssembly objects.
    /// This file is only written once and can be changed.  The Def file
    /// attached to this as a dependent is rewritten with each regeneration
    /// and contains the standard tests for DMAssembly.
    /// Regenerate this test project whenever there have been changes to the
    /// business objects.
    /// If tests are failing due to a unique setup in your application,
    /// you can either override the Create methods in TestUtils, or you
    /// can add the test to the ignore list below and reimplement it here.
    /// </summary>
    public partial class TestDMAssembly
    {

        [SetUp]
        public override void SetupTest()
        {
            //Runs every time that any testmethod is executed
            base.SetupTest();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //Code that is executed before any test is run in this class. If multiple tests
            // are executed then it will still only be called once.
            base.SetupFixture();
        }

        [TearDown]
        public override void TearDownTest()
        {
            //runs every time any testmethod is complete
            base.TearDownTest();
        }
        [Test]
        public void Test_InsertNewProjectAssemblyInfo_Invalid()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = new DMAssembly();

            //---------------Assert Precondition----------------
            Assert.IsTrue(dmAssembly.Status.IsNew);

            //---------------Execute Test ----------------------
            try
            {
                dmAssembly.Save();
                Assert.Fail("expected Err");
            }
            //---------------Test Result -----------------------
            catch (BusObjectInAnInvalidStateException ex)
            {
                StringAssert.Contains("Name' is a compulsory field and has no value", ex.Message);
                StringAssert.Contains("Solution ID' is a compulsory field and has no value", ex.Message);
            }
            Assert.IsTrue(dmAssembly.Status.IsNew);
        }

        [Test]
        public void Test_InsertNewProjectAssemblyInfo()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsShared.CreateUnsavedValidProjectAssemblyInfo();

            //---------------Assert Precondition----------------
            Assert.IsTrue(dmAssembly.Status.IsNew);

            //---------------Execute Test ----------------------
            dmAssembly.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(dmAssembly.Status.IsNew);
        }


        [Test]
        public void Test_DeleteProjectAssemblyInfo()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsShared.CreateDMAssembly();

            //---------------Assert Precondition----------------
            Assert.IsFalse(dmAssembly.Status.IsNew);
            string message;
            Assert.IsTrue(dmAssembly.IsDeletable(out message));

            //---------------Execute Test ----------------------
            dmAssembly.MarkForDelete();
            dmAssembly.Save();

            //---------------Test Result -----------------------  
            Assert.IsTrue(dmAssembly.Status.IsNew);
            Assert.IsTrue(dmAssembly.Status.IsDeleted);
        }

        [Test]
        public void Test_UpdateProjectAssemblyInfo()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsShared.CreateDMAssembly();

            //---------------Assert Precondition----------------
            Assert.IsFalse(dmAssembly.Status.IsNew);
            string message;
            Assert.IsTrue(dmAssembly.IsEditable(out message));

            //---------------Execute Test ----------------------
            dmAssembly.Name = TestUtilsShared.GetRandomString();
            dmAssembly.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(dmAssembly.Status.IsNew);
        }

        [Test]
        public void Test_ToString_AssemblynameBOIsNull()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsDMAssembly.CreateUnsavedDefaultDMAssembly();
            dmAssembly.Name = "";
            //---------------Assert Precondition----------------
            TestUtilsShared.AssertStringEmpty(dmAssembly.Name, "dmAssembly.Name");
            //---------------Execute Test ----------------------
            string actualToString = dmAssembly.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(dmAssembly.AssemblyID.ToString(), actualToString);
        }
        [Test]
        public void Test_ToString_IDIsNull()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsDMAssembly.CreateUnsavedDefaultDMAssembly();
            dmAssembly.Name = ""; ;
            dmAssembly.AssemblyID = null;
            //---------------Assert Precondition----------------
            TestUtilsShared.AssertStringEmpty(dmAssembly.Name, "dmAssembly.Name");
            Assert.IsNull(dmAssembly.AssemblyID);
            //---------------Execute Test ----------------------
            string actualToString = dmAssembly.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual("-unnamed DMAssembly-", actualToString);
        }
        [Test]
        public void Test_ToString()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsShared.CreateDMAssembly();

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string toString = dmAssembly.ToString();
            //---------------Test Result -----------------------
            Assert.AreEqual(toString, dmAssembly.Name);

        }

        [Test]
        public void Test_AssemblyName_FirstCharacterMustBeLetter()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = new DMAssembly();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            dmAssembly.AssemblyName = "1";
            //---------------Test Result -----------------------
            Assert.IsFalse(dmAssembly.Props["Name"].IsValid);
        }

        [Test]
        public void Test_IsDeletable_ShouldReturnTrueIfHasNoClasses()
        {
            //--------------- Set up test pack ------------------
            DMAssembly dmAssembly = TestUtilsShared.CreateDMAssembly();
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(0, dmAssembly.Classes.Count);
            //--------------- Execute Test ----------------------
            string message;
            bool isDeletable = dmAssembly.IsDeletable(out message);
            //--------------- Test Result -----------------------
            Assert.IsTrue(isDeletable);
            Assert.AreEqual("", message);
        }

        [Test]
        public void Test_IsDeletable_ShouldReturnFalseIfHasClasses()
        {
            //--------------- Set up test pack ------------------
            DMAssembly dmAssembly = TestUtilsShared.CreateDMAssembly();
            TestUtilsShared.CreateSavedDMClass(dmAssembly);
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(1, dmAssembly.Classes.Count);
            //--------------- Execute Test ----------------------
            string message;
            bool isDeletable = dmAssembly.IsDeletable(out message);
            //--------------- Test Result -----------------------
            Assert.IsFalse(isDeletable);
            StringAssert.Contains("The assembly '" + dmAssembly.ToString() + "' cannot be deleted as there are 1 objects related through the 'Classes' relationship that need to be deleted first.", message);

        }

        [Test]
        public void Test_DMAssemblyDuplicateClassNameRule_ShouldBeOnBusinessObject()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = new DMAssembly();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            ReadOnlyCollection<IBusinessObjectRule> rules = BOHelper.GetBusinessObjectRules(dmAssembly);
            //---------------Test Result -----------------------
            TestUtilsShared.AssertHasRuleOfType<DMAssemblyDuplicateClassNameRule>(rules);
        }

        [Test]
        public void Test_IsEditable_WhenNull_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = null;
            DMAssembly dmAssembly = TestUtilsShared.CreateDMAssembly();
            SetAssemblyName(dmAssembly, assemblyName);
            //---------------Assert Precondition----------------
            Assert.IsTrue(string.IsNullOrEmpty(assemblyName), "Assembly Name should be null");
            //            Assert.IsNull(propertyType.AssemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isEditable = dmAssembly.IsEditable(out message);
            //---------------Test Result -----------------------
            Assert.IsTrue(isEditable);
        }

        [Test]
        public void Test_IsEditable_WhenAssemblyNameStartsWithSystem_ShouldReturnFalse()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = "System";
            DMAssembly dmAssembly = TestUtilsShared.CreateDMAssembly();
            SetAssemblyName(dmAssembly, assemblyName);
            //---------------Assert Precondition----------------
            Assert.IsFalse(string.IsNullOrEmpty(assemblyName), "Assembly Name should not be null");
            Assert.AreEqual("System", assemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isEditable = dmAssembly.IsEditable(out message);
            //---------------Test Result -----------------------
            Assert.IsFalse(isEditable);
            StringAssert.Contains("The Assembly '" + dmAssembly.ToString() + "' cannot be edited.",message);
        } 
        
        [Test]
        public void Test_IsEditable_WhenAssemblyNameDoesNotStartsWithSystem_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            const string assemblyName = "Other";
            DMAssembly dmAssembly = TestUtilsShared.CreateDMAssembly();
            SetAssemblyName(dmAssembly, assemblyName);
            //---------------Assert Precondition----------------
            Assert.IsFalse(string.IsNullOrEmpty(assemblyName), "Assembly Name should not be null");
            Assert.AreNotEqual("System", assemblyName);
            //---------------Execute Test ----------------------
            string message;
            bool isEditable = dmAssembly.IsEditable(out message);
            //---------------Test Result -----------------------
            Assert.IsTrue(isEditable);
           
        }

        private void SetAssemblyName(DMAssembly assembly, string name)
        {
            assembly.AssemblyName = name;
        }


        



        #region Generator Methods
        [Test]
        public void Test_SetParent()
        {
            //---------------Set up test pack-------------------
            IModelSolution modelSolution = new DMSolution(TestUtilsShared.GetRandomString());
            IModelAssembly modelAssembly = new DMAssembly(TestUtilsShared.GetRandomString());
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            modelAssembly.Parent = modelSolution;

            //---------------Test Result -----------------------
            Assert.AreEqual(modelSolution, modelAssembly.Parent);
        }

        [Test]
        public void Test_AssemblyName()
        {
            //---------------Set up test pack-------------------

            string assemblyName = TestUtilsShared.GetRandomString();
            IModelAssembly modelAssembly = new DMAssembly(assemblyName);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            modelAssembly.AssemblyName = assemblyName;

            //---------------Test Result -----------------------
            Assert.AreEqual(assemblyName, modelAssembly.AssemblyName);

        }

        [Test]
        public void Test_SetClasses()
        {
            //---------------Set up test pack-------------------
            DMAssembly modelAssembly = new DMAssembly(TestUtilsShared.GetRandomString());
            DMClass dmClass1 = new DMClass();
            modelAssembly.Classes.Add(dmClass1);
            DMClass dmClass2 = new DMClass();
            modelAssembly.Classes.Add(dmClass2);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IList<IModelClass> classes = ((IModelAssembly)modelAssembly).ModelClasses;
            //---------------Test Result -----------------------
            Assert.AreEqual(2, classes.Count);
            Assert.IsTrue(classes.Contains(dmClass1), "The first class should be contained in the collection");
            Assert.IsTrue(classes.Contains(dmClass2), "The second class should be contained in the collection");
        }


        #endregion

    }
}